package com.example.inspurfabricapp.config;

import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.gateway.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * 超级账本结构网关配置
 *
 * @author lijiahao
 * @date 2024/06/26
 */
@Configuration
@Slf4j
public class HyperLedgerFabricGatewayConfig {

    @Resource
    private HyperLedgerFabricProperties hyperLedgerFabricProperties;

    @Bean
    public Gateway gateway() throws Exception {
        X509Certificate certificate = readX509Certificate(Paths.get(hyperLedgerFabricProperties.getCertificatePath()));
        PrivateKey privateKey = getPrivateKey(Paths.get(hyperLedgerFabricProperties.getPrivateKeyPath()));
        Wallet wallet = Wallets.newInMemoryWallet();
        wallet.put("user1", Identities.newX509Identity("Org1MSP", certificate, privateKey));

        //根据connection.json 获取Fabric网络连接对象
        Gateway.Builder builder = Gateway.createBuilder()
                .identity(wallet, "user1")
                .networkConfig(Paths.get(hyperLedgerFabricProperties.getNetworkConnectionConfigPath()));
        //连接网关
        Gateway gateway = builder.connect();
        log.info("============== connected fabric gateway {} ", gateway);

        return gateway;
    }

    private X509Certificate readX509Certificate(final Path certificatePath) throws IOException, CertificateException {
        try (Reader certificateReader = Files.newBufferedReader(certificatePath, StandardCharsets.UTF_8)) {
            return Identities.readX509Certificate(certificateReader);
        }
    }

    private PrivateKey getPrivateKey(final Path privateKeyPath) throws IOException, InvalidKeyException {
        try (Reader privateKeyReader = Files.newBufferedReader(privateKeyPath, StandardCharsets.UTF_8)) {
            return Identities.readPrivateKey(privateKeyReader);
        }
    }

    @Bean
    public Network network(Gateway gateway) {
        return gateway.getNetwork(hyperLedgerFabricProperties.getChannel());
    }

    @Bean
    public Contract catContract(Network network) {
        return network.getContract(hyperLedgerFabricProperties.getContractName());
    }

    @Bean
    public ChaincodeEventListener chaincodeEventListener(Contract contract) {
        return new ChaincodeEventListener(contract);
    }

}
